home *** CD-ROM | disk | FTP | other *** search
- /*
- * This software is copyright 1992 by Robert Morris.
- * You may freely redistribute this software as shareware
- * if you do so in the same form as you got it. If you find
- * this software useful, please send $12 to:
- * Robert Morris
- * P.O. Box 1044
- * Harvard Square Station
- * Cambridge, MA 02238
- * ecognome@aol.com
- * If you incorporate any of this software in any kind of
- * commercial product, please send $2 per copy distributed
- * to the above address.
- */
-
- #include "tiffinfo.h"
-
- /*
- * Lempel-Ziv decompression for TIFF. inlen is the actual number of input
- * characters, and outlen is the number of expected output characters.
- * out[] has size outlen, so it is an error if there are more than outlen
- * characters produced. UnLZW() returns 0 if everything was fine, and
- * < 0 if there was some problem.
- */
-
- /*
- * If a code is < 256, it is that character. 256 is the Clear code, and
- * 257 is the end-of-information code. Otherwise it refers to a string
- * previously produced as output, followed by a single character.
- */
- struct stringtable{
- long index;
- long len;
- };
- #define ClearCode 256
- #define EndOfInformation 257
-
- void
- ClearTable(struct stringtable *table)
- {
- int i;
-
- for(i = 0; i < 256; i++){
- table[i].index = 0;
- table[i].len = 0;
- }
- }
-
- int
- UnLZW(char *in, long inlen, char *out, long outlen)
- {
- struct stringtable *table = 0;
- int ncodes; /* # of codes in the table */
- int codelen; /* current code length in bits */
- unsigned short *ip; /* current point in input */
- int bit; /* # of (high) bits consumed in *ip */
- char *op; /* next element to write in out[] */
- unsigned short code;
- int i;
-
- table = (struct stringtable *) NewPtr(sizeof(struct stringtable) * 4096);
- if(table == 0)
- return(MemError());
-
- ClearTable(table);
- ncodes = 258; /* one for each 8-bit character, plus two special codes */
- codelen = 9;
-
- op = out;
- ip = (unsigned short *) in;
- bit = 0;
-
- while(1){
- if((char *)ip >= in + inlen){
- /* ran out of information before we saw EndOfInformation! */
- goto bad;
- }
-
- if(bit >= 16){
- ip++;
- bit = 0;
- }
- code = (*ip << bit) >> (16 - codelen);
- bit += codelen;
- if(bit > 16){
- /* need to read some more */
- ip++;
- bit -= 16;
- code |= (*ip >> (16 - bit));
- }
-
- if(code == ClearCode){
- ncodes = 258;
- codelen = 9;
- } else if(code == EndOfInformation){
- break;
- } else if(code < ncodes){
- if(op + table[code].len > out + outlen)
- goto bad;
- table[ncodes].index = op - out;
- if(code < 256){
- *op++ = code;
- table[ncodes].len = 2;
- } else {
- for(i = 0; i < table[code].len; i++)
- *op++ = out[table[code].index + i];
- table[ncodes].len = table[code].len + 1;
- }
- ncodes++;
- if(ncodes == (1 << codelen))
- codelen++;
- } else {
- /* code out of range */
- goto bad;
- }
- }
-
- DisposPtr(table);
- return(0);
- bad:
- if(table)
- DisposPtr(table);
- return(-1);
- }